package edu.mapi.aamas.renderer;

import java.awt.Font;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;

import javax.media.j3d.Appearance;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.LineArray;
import javax.media.j3d.RenderingAttributes;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TransparencyAttributes;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Cylinder;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.geometry.Text2D;

/**
 * 
 * @author rjpg
 *
 */
public class Util3D {

	/* (non-Javadoc)
	 * @see pt.up.fe.dceg.neptus.mp.MapChangeListener#mapChanged(pt.up.fe.dceg.neptus.mp.MapChangeEvent)
	 */
	public static Box foundBox(TransformGroup model)
	{
		
		Enumeration childs=model.getAllChildren();
		while(childs.hasMoreElements())
		{
			Object child = childs.nextElement();
			if(child instanceof Box)
			{
				return (Box)child; 	
			}
			else if (child instanceof TransformGroup)
			{
				return foundBox((TransformGroup)child);
			}
			
		}
		return null;
	}
	
	public static Sphere foundSphere(TransformGroup model)
	{
		
		Enumeration childs=model.getAllChildren();
		while(childs.hasMoreElements())
		{
			Object child = childs.nextElement();
			if(child instanceof Sphere)
			{
				//System.out.println("-------------FOUND-------------");
				return (Sphere)child; 	
			}
			else if (child instanceof TransformGroup)
			{
				return foundSphere((TransformGroup)child);
			}
			
		}
		return null;
	}
	
	public static Cylinder foundCylinder(TransformGroup model)
	{
		
		Enumeration childs=model.getAllChildren();
		while(childs.hasMoreElements())
		{
			Object child = childs.nextElement();
			if(child instanceof Cylinder)
			{
				//System.out.println("-------------FOUND-------------");
				return (Cylinder)child; 	
			}
			else if (child instanceof TransformGroup)
			{
				return foundCylinder((TransformGroup)child);
			}
			
		}
		return null;
	}
	
	public static TransformGroup makeAxis(boolean leters,double size)
	{
		TransformGroup model= new TransformGroup();
    	Sphere	sphere=new Sphere(0.25f);
    	
    	RenderingAttributes renderingAttributes = new RenderingAttributes(
	                 true,                                                       // boolean depthBufferEnable, 
	                 true,                                                           // boolean depthBufferWriteEnable, 
	                 1.0f,                                                           // float alphaTestValue,
	                 RenderingAttributes.ALWAYS,             // int alphaTestFunction,
	                 true,                                                           // boolean visible,
	                 true,                                   // boolean ignoreVertexColors, 
	                 false,                                                      // boolean rasterOpEnable,
	                 RenderingAttributes.ROP_COPY            // int rasterOp
	                 );
    	Color3f c=new Color3f(1.0f,1.0f,1.0f);
    	ColoringAttributes coloringAttributes = new ColoringAttributes(c,ColoringAttributes.SHADE_GOURAUD);
    	
    	Point3d listp1[]=new Point3d[2];
    	listp1[0]=new Point3d(size,0.0,0.0);
    	listp1[1]=new Point3d(0.,0.0,0.0);
    	
    	//listp1[1]=new Point3d(-2,0.0,0.0);
    	
    	Point3d listp2[]=new Point3d[2];
    	listp2[0]=new Point3d(0.0,size,0.0);
    	listp2[1]=new Point3d(0.0,0.0,0.0);
    	
    	//listp2[1]=new Point3d(0.0,-2,0.0);
    	
    	Point3d listp3[]=new Point3d[2];
    	
    	listp3[0]=new Point3d(0.0,0.0,size);
    	listp3[1]=new Point3d(0.0,0.0,0.0);
    	
    	//listp3[1]=new Point3d(0.0,0.0,-2.);
    	
    	LineArray myLines1 = new LineArray(
     			listp1.length,
				LineArray.COORDINATES);
    	myLines1.setCoordinates( 0, listp1 );
    	
    	LineArray myLines2 = new LineArray(
     			listp1.length,
				LineArray.COORDINATES);
    	myLines2.setCoordinates( 0, listp2 );
    	LineArray myLines3 = new LineArray(
     			listp1.length,
				LineArray.COORDINATES);
    	myLines3.setCoordinates( 0, listp3 );
    	
    	Appearance appearance1 = new Appearance();
      	appearance1.setRenderingAttributes(renderingAttributes);
      	c=new Color3f(1.0f,0.0f,0.0f);
      	coloringAttributes = new ColoringAttributes(c,ColoringAttributes.SHADE_GOURAUD);
      	appearance1.setColoringAttributes(coloringAttributes);
    	Shape3D shape3D1 = new Shape3D(myLines1,appearance1);
    	
    	Appearance appearance2 = new Appearance();
      	appearance2.setRenderingAttributes(renderingAttributes);
      	c=new Color3f(0.0f,1.0f,0.0f);
      	coloringAttributes = new ColoringAttributes(c,ColoringAttributes.SHADE_GOURAUD);
      	appearance2.setColoringAttributes(coloringAttributes);
    	Shape3D shape3D2 = new Shape3D(myLines2,appearance2);
    	
    	Appearance appearance3 = new Appearance();
      	appearance3.setRenderingAttributes(renderingAttributes);
      	c=new Color3f(0.3f,0.3f,1.0f);
      	coloringAttributes = new ColoringAttributes(c,ColoringAttributes.SHADE_GOURAUD);
      	appearance3.setColoringAttributes(coloringAttributes);
    	Shape3D shape3D3 = new Shape3D(myLines3,appearance3);
    	
    	
    	
    	c=new Color3f(1.0f,1.0f,1.0f);
    	coloringAttributes = new ColoringAttributes(c,ColoringAttributes.SHADE_GOURAUD);
    	Appearance appearance4 = new Appearance();
    	appearance4.setRenderingAttributes(renderingAttributes);
      	appearance4.setColoringAttributes(coloringAttributes);
      	TransparencyAttributes trans=new TransparencyAttributes();
    	trans.setTransparency(0.3f);
    	trans.setTransparencyMode(TransparencyAttributes.BLEND_ONE);
    	appearance4.setTransparencyAttributes(trans);
      	sphere.setAppearance(appearance4);
      	
    	Transform3D t=new Transform3D();
    	t.setScale(0.1);
    	model.setTransform(t);
    	model.addChild(shape3D1);
    	model.addChild(shape3D2);
    	model.addChild(shape3D3);
    	//model.addChild(sphere);
    	
    	if (leters)
    	{
    	//-------------------------XX
    	TransformGroup xtextTrans=new TransformGroup();
    	Transform3D xtrans2 = new Transform3D();
        xtrans2.setTranslation(new Vector3d(2.,0.,0.));
        xtextTrans.setTransform(xtrans2);        
         
         // Text2D (java.lang.String text, Color3f color,
         //        java.lang.String fontName, int fontSize, int fontStyle)         
         Text2D xtext2D = new Text2D("X",
                                    new Color3f(1f, 0f, 0f),
                                    "Helvetica", 100, Font.BOLD | Font.ITALIC);
         xtextTrans.setTransform(xtrans2);
         xtextTrans.addChild(xtext2D);
         
         TransformGroup xtextTrans2=new TransformGroup();
         Transform3D xtrans3 = new Transform3D();
         
         
         xtrans3.rotX(Math.PI);
         xtrans2.mul(xtrans3);
         Text2D xtext2D2 = new Text2D("X",
                 new Color3f(1f, 0f, 0f),
                 "Helvetica", 100, Font.BOLD | Font.ITALIC);
        
         xtextTrans2.setTransform(xtrans2);
         xtextTrans2.addChild(xtext2D2);

         /*Appearance appGFront = new Appearance();
 		 PolygonAttributes p = new PolygonAttributes ();
    	 p.setCullFace (PolygonAttributes.CULL_NONE);
    	 appGFront.setPolygonAttributes(p);
    	text2D.setAppearance(appGFront);*/
    	
         model.addChild(xtextTrans);
         model.addChild(xtextTrans2);
          
         //---------------------yy
         TransformGroup ytextTrans=new TransformGroup();
     	 Transform3D ytrans2 = new Transform3D();
     	 
     	 
         ytrans2.setTranslation(new Vector3d(0.,2.,0.));
         
         ytextTrans.setTransform(ytrans2);        
          
          // Text2D (java.lang.String text, Color3f color,
          //        java.lang.String fontName, int fontSize, int fontStyle)         
          Text2D ytext2D = new Text2D("Y",
                                     new Color3f(0f, 1f, 0f),
                                     "Helvetica", 100, Font.BOLD | Font.ITALIC);
          ytextTrans.setTransform(ytrans2);
          ytextTrans.addChild(ytext2D);
          
          TransformGroup ytextTrans2=new TransformGroup();
          Transform3D ytrans3 = new Transform3D();
          
          
          ytrans3.rotY(Math.PI);
          ytrans2.mul(ytrans3);
          Text2D ytext2D2 = new Text2D("Y",
                  new Color3f(0f, 1f, 0f),
                  "Helvetica", 100, Font.BOLD | Font.ITALIC);
         
          ytextTrans2.setTransform(ytrans2);
          ytextTrans2.addChild(ytext2D2);

          /*Appearance appGFront = new Appearance();
  		 PolygonAttributes p = new PolygonAttributes ();
     	 p.setCullFace (PolygonAttributes.CULL_NONE);
     	 appGFront.setPolygonAttributes(p);
     	text2D.setAppearance(appGFront);*/
     	
          model.addChild(ytextTrans);
          model.addChild(ytextTrans2);
          
          //----------------------------zz
          TransformGroup ztextTrans=new TransformGroup();
      	Transform3D ztrans2 = new Transform3D();
      	Transform3D ztrans3 = new Transform3D();
          ztrans2.setTranslation(new Vector3d(0.,0.,2.));
          ztrans3.rotY(Math.PI/2);
          ztrans2.mul(ztrans3);
          ztextTrans.setTransform(ztrans2);        
           
           // Text2D (java.lang.String text, Color3f color,
           //        java.lang.String fontName, int fontSize, int fontStyle)         
           Text2D ztext2D = new Text2D("Z",
                                      new Color3f(0.7f, 0.7f, 1f),
                                      "Helvetica", 100, Font.BOLD | Font.ITALIC);
           ztextTrans.setTransform(ztrans2);
           ztextTrans.addChild(ztext2D);
           
           TransformGroup ztextTrans2=new TransformGroup();
           
           
           ztrans3.rotX(Math.PI);
           ztrans2.mul(ztrans3);
           
           Text2D ztext2D2 = new Text2D("Z",
                   new Color3f(0.7f, 0.7f, 1f),
                   "Helvetica", 100, Font.BOLD | Font.ITALIC);
          
           ztextTrans2.setTransform(ztrans2);
           ztextTrans2.addChild(ztext2D2);

           /*Appearance appGFront = new Appearance();
   		 PolygonAttributes p = new PolygonAttributes ();
      	 p.setCullFace (PolygonAttributes.CULL_NONE);
      	 appGFront.setPolygonAttributes(p);
      	text2D.setAppearance(appGFront);*/
      	
           model.addChild(ztextTrans);
           model.addChild(ztextTrans2);
    	}
         
         
    	
		return model;
	}
	
    /**
     * @param inStream
     * @param outStream
     * @return
     */
    public static boolean copyStreamToStream (InputStream inStream, OutputStream outStream)
    {
		try
        {
		    //FIX ME Ver melhor o que isto faz
		    //ProgressMonitorInputStream _in = new ProgressMonitorInputStream(
            //        new JFrame(), "Downloading ", inStream);
		    //int ii = inStream.available();
            byte[] extra = new byte[50000];

            int ret = 0;
            int pos = 0;

            //zTeste.zOutStream.putNextEntry(zTeste.zEntry);
            for (;;)
            {
            	ret = inStream.read(extra);
       
            	if (ret != -1)
            	{
            	    byte[] extra1 = new byte[ret];
					System.arraycopy (extra, 0 , extra1, 0 , ret);					
            	    outStream.write (extra1);
            		outStream.flush();
            		pos =+ret;
       
            	}
            	else
            	{
       
            		break;
            	}
            }
            return true;
        }
        catch (IOException e)
        {
       
            //e.printStackTrace();
            return false;
        }
    }

    
    /**
     * @param inStream
     * @return
     */
    public static String copyStreamToString (InputStream inStream)
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        copyStreamToStream(inStream, baos);
        String ret = baos.toString();
        return ret;
    }

    
    
    /**
     * @param inStream
     * @param outFile
     * @return
     */
    public static boolean copyStreamToFile (InputStream inStream, File outFile)
    {
        try
        {
            FileOutputStream fos = new FileOutputStream(outFile);
            return copyStreamToStream(inStream, fos);
        }
        catch (Exception e) 
        {
          
            return false;
        }
    }
    
    
    
    /**
     * @param inStream
     * @return
     */
    public static File copyStreamToTempFile (InputStream inStream)
    {
        File fx;
        try
        {
        	File tmpDir = new File(System.getProperty("java.io.tmpdir","tmp"));
            fx = File.createTempFile("neptus_", "tmp", tmpDir);
            boolean ret = copyStreamToFile (inStream, fx);
            if (ret)
                return fx;
            else
                return null;
        }
        catch (IOException e)
        {
            //ConfigFetch.logPub.error("copyStreamToTempFile", e);
            return null;
        }
    }
	
}
